home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1995 October
/
EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso
/
Aminet
/
util
/
moni
/
CPULoad_JS.lha
/
CPULoad.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-29
|
11KB
|
414 lines
/*
CPULoad
(C) Thomas Radtke 1994
main: Process, Initialisierungen und buisy loop
druck: Task, Graphische Ausgabe
IdleIrq: IRQ server, Auswertung des buisy loop
Um double-Rechnungen zu vermeiden werden ULONG's in beide Richtungen
geshiftet. Bei hohen Rechenleistungen kann dies ggf. zu Überläufen
führen. Abhilfe bringt eine Verringerung des 'aktuell'-Wertes
('aktuell>>n') um ein geeignetes n.
Das Abbruchsignal ist CTRL-D. Niemals CTRL-C verwenden, wenn der
Compiler dieses Signal als generellen Abbruch benutzt.
Basiert auf Idle LED von Lindsay Meek.
read the README !
Version 1.1 modifications (Mar-26-95) by Jean-Guy Speton:
- Fixed source to compile with DICE 3.0, which mainly involved the
insertion of __geta4 for IdleCPU() and druck().
- Added prototype #include's, removed local protypes of system calls,
which made my system crash. :-(
- Changed comments to C++ style, which I prefer, and deleted some
German comments which I didn't understand. Apologies to Thomas.
- cast'ed system calls to get rid of compiler warnings.
- Replaced explicit priority changes with calls to SetTaskPri().
- Replaced explicit signal changes and queries with SetSignal().
- Window now opened with OpenWindowTags rather than OpenWindow().
- Changed expensive GIMMEZEROZERO window to non-GZZ window.
- Changed CTRL-D handling to CTRL-C, so you can 'break' it from a CLI.
- Added hash lines at 1/4, 1/2 and 3/4 the way down the window.
Set the colour yourself if you don't like mine by changing HASH_PEN.
- Removed sizing gadget and added zip gadget, the way I like it.
(I thought the sizing gadget made the window look ugly.)
- Added command line options LEFT, TOP, WIDTH and HEIGHT to specify
initial location and size of window.
- Added UPDATE command line option, which sets how often the graph is
updated. ie. Update every UPDATE seconds. Default is 1.
*/
const char *dummy="$VER: CPULoad 1.1";
#include <intuition/intuitionbase.h>
#include <exec/nodes.h>
#include <exec/tasks.h>
#include <exec/interrupts.h>
#include <hardware/intbits.h>
#include <libraries/dos.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <clib/alib_protos.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/dos_protos.h>
__geta4 void druck(void);
__geta4 int IdleCPU(void);
#define HASH_PEN 0 // Pen used for hash lines.
// Template string and variables used for command line arguments.
#define TEMPLATE "L=LEFT/N,T=TOP/N,W=WIDTH/N,H=HEIGHT/N,U=UPDATE/N"
LONG WIN_LEFT, WIN_TOP, WIN_WIDTH, WIN_HEIGHT, UPDATE;
BOOL must_quit = FALSE;
// Stacksize für den Grafik-Task (1000 < STACK_SIZE < 10000)
#define STACK_SIZE 4000L
struct Task *task = NULL;
char *taskname = "CPULoad";
struct timerequest *tr;
struct MsgPort *tport;
struct Message *msg;
struct Window *CustWindow;
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
#define rp CustWindow->RPort
#define bl CustWindow->BorderLeft
#define bt CustWindow->BorderTop
#define br CustWindow->BorderRight
#define bb CustWindow->BorderBottom
#define ww CustWindow->Width
#define wh CustWindow->Height
unsigned int maximum,aktuell;
struct Task *met2;
#define UTILITY_NAME "IdleCPU"
// Various counters used to detect the idle state in the vblank.
static ULONG idle_vbi_cnt_limit[3];
struct timerequest *create_timer(ULONG unit)
{
LONG error;
struct MsgPort *timerport;
struct timerequest *timermsg;
if ((timerport = (struct MsgPort *)CreatePort(0,0)) == NULL)
exit(1);
if ((timermsg = (struct timerequest *)CreateExtIO(timerport,sizeof(struct timerequest))) == NULL)
exit(1);
if ((error = OpenDevice(TIMERNAME,unit,(struct IORequest *)timermsg,0)) != 0)
exit(1);
return(timermsg);
}
__geta4 int IdleCPU() {
idle_vbi_cnt_limit[0] = 1;
aktuell = idle_vbi_cnt_limit[1];
idle_vbi_cnt_limit[1] = 0;
return 0;
}
__geta4 void druck() {
struct IntuiMessage *message;
struct timeval updateval;
LONG n;
unsigned int sum;
LONG height,width,left,right,top,bottom;
ULONG int_pix_per_load;
int whitepen,blackpen;
struct Screen *PubScreen;
short pen,minpen,maxpen;
unsigned short RGB;
int class;
// init timer
tr = create_timer(UNIT_MICROHZ);
updateval.tv_secs=0;
updateval.tv_micro=100000; /* 1/10 secs */
IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);
GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0);
PubScreen = LockPubScreen(NULL);
WORD zoom_words[4] = {WIN_LEFT, WIN_TOP, WIN_WIDTH, PubScreen->WBorTop + PubScreen->Font->ta_YSize + 1};
CustWindow = OpenWindowTags(NULL,
WA_Left, WIN_LEFT,
WA_Top, WIN_TOP,
WA_Width, WIN_WIDTH,
WA_Height, WIN_HEIGHT,
WA_MinWidth,50,
WA_MinHeight,25,
WA_IDCMP, CLOSEWINDOW | NEWSIZE | CHANGEWINDOW,
WA_Flags, ACTIVATE | SMART_REFRESH | WINDOWCLOSE | WINDOWDRAG | WINDOWDEPTH,
WA_Title, "CPULoad",
WA_PubScreen,PubScreen,
WA_Zoom, zoom_words,
NULL);
UnlockPubScreen(NULL,PubScreen);
CustWindow->MinHeight = bt;
whitepen = 1;
blackpen = 0;
maxpen = 0x000;
minpen = 0xfff;
for (n = 0; n < (1 << PubScreen->BitMap.Depth); n++) {
RGB = GetRGB4(PubScreen->ViewPort.ColorMap,n);
pen = (RGB & 0x00f) + ((RGB & 0x0f0) >> 4) + ((RGB & 0xf00) >> 8);
if (pen < minpen) {
minpen = pen;
blackpen = n;
}
if (pen > maxpen) {
maxpen = pen;
whitepen = n;
}
}
height = wh - bt - bb;
width = ww - br - bl;
left = bl;
right = left + width - 1;
top = bt;
bottom = bt + height - 1;
SetAPen(rp,whitepen);
RectFill(rp,left,top,right,bottom);
SetAPen(rp, HASH_PEN);
Move(rp, left, top + height/4);
Draw(rp, right, top + height/4);
Move(rp, left, top + height/2);
Draw(rp, right, top + height/2);
Move(rp, left, top + 3*height/4);
Draw(rp, right, top + 3*height/4);
while (1) {
if (must_quit) {
Signal(met2, SIGBREAKF_CTRL_D);
Wait(0L);
}
sum = 0;
for (n = 0; n < 10; n++) {
sum += aktuell;
updateval.tv_micro = 100000 * UPDATE;
tr->tr_node.io_Command = TR_ADDREQUEST;
tr->tr_time = updateval;
DoIO((struct IORequest *)tr);
}
sum /= 10; // Average over 10 samples.
if (wh > bt) {
height = wh - bt - bb;
width = ww - br - bl;
left = bl;
right = left + width - 1;
top = bt;
bottom = bt + height - 1;
int_pix_per_load = (height<<16)/maximum;
ScrollRaster(rp,1,0,left,top,right,bottom);
Move(rp,right,bottom);
SetAPen(rp,blackpen);
Draw(rp, right, top + ((sum * int_pix_per_load) >> 16));
if (rp->cp_y > top) {
SetAPen(rp,whitepen);
Draw(rp,right,top);
}
// Fill in the displaced hash-line points.
SetAPen(rp, HASH_PEN);
Move(rp, right, top + height/4);
Draw(rp, right, top + height/4);
Move(rp, right, top + height/2);
Draw(rp, right, top + height/2);
Move(rp, right, top + 3*height/4);
Draw(rp, right, top + 3*height/4);
}
while (message = (struct IntuiMessage *)GetMsg(CustWindow->UserPort)) {
if ((class = message->Class) == CLOSEWINDOW) {
ReplyMsg((struct Msg *)message);
Signal(met2, SIGBREAKF_CTRL_C);
Signal(met2, SIGBREAKF_CTRL_D);
SetTaskPri(met2, 1L); // So it doesn't have to wait if CPU usage is 100%.
Wait(0L); // Parent process will DeleteTask() us.
}
else if (class == NEWSIZE) {
ReplyMsg((struct Msg *)message);
if (wh > bt) {
SetAPen(rp,whitepen);
RectFill(rp,left,top,right,bottom);
SetAPen(rp, HASH_PEN);
Move(rp, left, top + height/4);
Draw(rp, right, top + height/4);
Move(rp, left, top + height/2);
Draw(rp, right, top + height/2);
Move(rp, left, top + 3*height/4);
Draw(rp, right, top + 3*height/4);
}
}
else if (class == CHANGEWINDOW)
ReplyMsg((struct Msg *)message);
}
}
}
// Run this as a process. It aborts when it detects a CTRL_C signal.
main()
{
struct Task *met;
struct Interrupt mei;
WORD oldpri;
char *oldname;
struct RdArgs *ra;
LONG args[5] = { 0L, 0L, 0L, 0L, 0L };
// Switch off CTRL_C handling, we'll handle it ourselves.
signal(SIGINT,SIG_IGN);
// Read command-line arguments.
if (ra = ReadArgs(TEMPLATE, args, NULL)) {
WIN_LEFT = (args[0] ? *(LONG *)args[0] : 0);
WIN_TOP = (args[1] ? *(LONG *)args[1] : 0);
WIN_WIDTH = (args[2] ? *(LONG *)args[2] : 130);
WIN_HEIGHT = (args[3] ? *(LONG *)args[3] : 100);
UPDATE = (args[4] ? *(LONG *)args[4] : 1);
if (UPDATE < 1) // A value of 0 would be unacceptable.
UPDATE = 1;
FreeArgs(ra);
}
else
exit(1);
// Remove CPULoad if already present.
if (met = FindTask(UTILITY_NAME)) {
Signal(met,SIGBREAKF_CTRL_C);
exit(0);
}
// Setup for IRQ
mei.is_Node.ln_Type = NT_INTERRUPT;
mei.is_Node.ln_Pri = -127;
mei.is_Node.ln_Name = UTILITY_NAME;
mei.is_Data = (APTR)0; // idle_vbi_cnt_limit;
mei.is_Code = (void *)IdleCPU;
AddIntServer(INTB_VERTB, &mei); // Install IRQ server.
met=FindTask(NULL);
oldname=met->tc_Node.ln_Name; // Save old name.
met->tc_Node.ln_Name=UTILITY_NAME;
oldpri = SetTaskPri(met, 40);
met2 = met; // Pointer for druck().
// Reset counters.
idle_vbi_cnt_limit[0]=0;
idle_vbi_cnt_limit[1]=0;
idle_vbi_cnt_limit[2]=0;
// Wait for next vbi, nicht ganz astrein.
Forbid();
while(idle_vbi_cnt_limit[0] == 0) ;
// Count # of increments in one frame (for calibration).
idle_vbi_cnt_limit[2] = 0;
idle_vbi_cnt_limit[0] = 0;
while (idle_vbi_cnt_limit[0] == 0)
idle_vbi_cnt_limit[2]++;
Permit();
// druck() braucht maximum
maximum = idle_vbi_cnt_limit[2];
// printf("%d\n",maximum); fflush(stdout);
task = CreateTask(taskname,30,druck,STACK_SIZE);
SetTaskPri(met, -127);
// Busy loop for eating up idle CPU cycles.
SetSignal(0L, SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D); // Ignore queued CTRL_C and CTRL_D.
while((met->tc_SigRecvd & SIGBREAKF_CTRL_C) == 0) // Abort on CTRL_C
idle_vbi_cnt_limit[1]++; // Increment idle counter
// We cannot remove the child if it's waiting for timer IO
// so we wait for it to send us a CTRL_D, which means it
// is ready to be killed.
must_quit = TRUE; // Let the task know it must quit.
Wait(SIGBREAKF_CTRL_D);
RemIntServer(INTB_VERTB,&mei); // Remove IRQ server.
SetTaskPri(met, oldpri);
met->tc_Node.ln_Name=oldname; // Change name back.
if (tr) {
CloseDevice((struct IORequest *)tr);
DeleteExtIO((struct IORequest *)tr);
}
if (CustWindow)
CloseWindow(CustWindow);
DeleteTask(task);
if (IntuitionBase)
CloseLibrary((struct Library *)IntuitionBase);
if (GfxBase)
CloseLibrary(GfxBase);
exit(0);
}